package com.lj.infoisland.service;

import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @version 1.0.0
 * @description minio启动时创建bucket
 * @date 2024/4/4 14:00
 * @created by Guoshun
 */
@Slf4j
@Component
public class MinioService {

    @Resource
    private MinioClient minioClient;

    @Value("${minio.bucket}")
    private String bucketName;

    /**
     * 创建bucket
     *
     * @return Boolean true成功 false 失败
     */
    @PostConstruct
    public Boolean createBucket() {
        BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder()
                .bucket(bucketName).build();
        try {
            boolean existsFlag = minioClient.bucketExists(bucketExistsArgs);
            if (!existsFlag) {
                MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();
                minioClient.makeBucket(makeBucketArgs);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("Minio的bucket初始化失败{}", bucketName);
            return false;
        }
        return true;
    }

    /**
     * 文件上传
     *
     * @param inputStream
     * @param contentType
     * @param fileName
     * @return
     */
    public Boolean put(InputStream inputStream, String contentType, String fileName) throws IOException {
        try {
            PutObjectArgs stream = PutObjectArgs.builder()
                    .object(fileName)
                    .bucket(bucketName)
                    .contentType(contentType)
                    .stream(inputStream, inputStream.available(), -1).build();
            minioClient.putObject(stream);
            return true;
        } catch (Exception e) {
            log.error("文件上传失败，文件{}", fileName);
            throw new RuntimeException(e.getMessage());
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    /**
     * 获取文件的url地址
     * 支持版本管理后续增加
     *
     * @param fileName
     */
    public String getDownloadUrl(String fileName) {
        GetPresignedObjectUrlArgs presignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName).object(fileName).method(Method.GET).expiry(7 * 24 * 60 * 60).build();
        try {
            String downloadUrl = minioClient.getPresignedObjectUrl(presignedObjectUrlArgs);
            return downloadUrl;
        } catch (ServerException |
                 InsufficientDataException | ErrorResponseException |
                 IOException | NoSuchAlgorithmException | InvalidKeyException | InvalidResponseException |
                 XmlParserException | InternalException e) {
            log.error("文件下载失败{}", fileName);
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 获取文件流
     * 后续支持写入抬头
     *
     * @param fileName
     */
    public ByteArrayOutputStream getDownloadFile(String fileName) throws IOException {
        GetObjectArgs getObjectArgs = GetObjectArgs.builder().object(fileName).bucket(bucketName).build();
        byte[] buf = new byte[1024];
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
        try {
            GetObjectResponse downloadUrl = minioClient.getObject(getObjectArgs);
            int length = 0;
            while ((length = downloadUrl.read(buf)) > 0) {
                outputStream.write(buf, 0, length);
            }
            return outputStream;
        } catch (ServerException |
                 InsufficientDataException | ErrorResponseException |
                 IOException | NoSuchAlgorithmException | InvalidKeyException | InvalidResponseException |
                 XmlParserException | InternalException e) {
            log.error("文件下载失败{}", fileName);
            throw new RuntimeException(e.getMessage());
        } finally {
            outputStream.close();
        }
    }

    /**
     * 文件删除
     *
     * @param key
     */
    public boolean deleteFile(String key) {
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucketName).object(key).build();
        try {
            minioClient.removeObject(removeObjectArgs);
        } catch (ServerException |
                 InsufficientDataException | ErrorResponseException |
                 IOException | NoSuchAlgorithmException | InvalidKeyException | InvalidResponseException |
                 XmlParserException | InternalException e) {
            log.error("文件删除失败{}", key);
            throw new RuntimeException(e.getMessage());
        }
        return true;
    }

}

